#include <iostream>
#include <ctime>
#include <QRegExp>

#include "httpClient.h"
#include "server.h"

Server::Server(QObject * parent) : QObject(parent)
{
    connect(&server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));

    server.listen(QHostAddress::Any, 8888);
    printf("Server is listening at %d.\n", 8888);

    fl = new FileList;
    page = new webpage(fl);

}

QString Server::header(unsigned int status, unsigned int lenght)
{
    time_t rawtime;
    struct tm *timeinfo;
    char buffer[128];

    time(&rawtime);
    timeinfo = localtime(&rawtime);

    strftime(buffer, 128, "%a, %d %b %Y %H:%M:%S", timeinfo);

    QString str;
    QTextStream stream(&str, QIODevice::ReadWrite);
    stream  <<  "HTTP/1.1 200 OK\r\n"
            <<  "Expires: " << buffer << " GMT\r\n"
            <<  "Last-Modified: " << buffer << " GMT\r\n"
            <<  "Content-Type: text/html;\r\n"
            <<  "Date: " << buffer << " GMT\r\n"
            <<  "Server: hfsHTTPd\r\n"
            <<  "Cache-Control: private\r\n"
            <<  "Content-Length: " << lenght << "\r\n\r\n";

    stream.flush();

    return str;
}

Server::~Server()
{
    server.close();
    delete page;
    delete fl;
}

void Server::acceptConnection()
{
    QTcpSocket *cl = server.nextPendingConnection();
    http_client *client = new http_client(cl);
    clients.push_front(client);

    connect(cl, SIGNAL(readyRead()), this, SLOT(startRead()));
    connect(cl, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
}

void Server::dnc()
{
    http_client *client = LookFor(qobject_cast<QTcpSocket *>(sender()));
    if(client && !client -> header)
    {
        client -> socket -> close();
        printf("Client timeout'ed.\n");
    }
}

void Server::clientDisconnected()
{
    http_client *client = LookFor(qobject_cast<QTcpSocket *>(sender()));
    if(!client)
        return;

    if(clients.contains(client))
    {
        clients.removeAll(client);
    } else printf("Disconnected client not listed in clients list.\n");

    //delete client; //-- it's crashing
}

parsedQuery *Server::parseQuery(QString header)
{
    parsedQuery *wsk = new parsedQuery;
    {   // GET / HTTP/1.1
        QRegExp vpath("GET .[^\r\n]*\r\n");
        if(vpath.indexIn(header, 0))
            wsk-> vpath = vpath.cap(0);
    }

    {
        QRegExp useragent("\nUser-Agent: .[^\r\n]*s\r\n");
        if(useragent.indexIn(header, 0))
        {
            wsk-> useragent = useragent.cap(0);
            wsk-> useragent.remove(0, strlen("\nUser-Agent: "));
            wsk-> useragent.remove(wsk-> useragent.size()-2, 2);
        }
    }

    {
        QRegExp referer("\nReferer: .[^\r\n]*\r\n");
        if(referer.indexIn(header, 0))
        {
            wsk-> referer = referer.cap(0);
            wsk-> referer.remove(0, strlen("\nReferer: "));
            wsk-> referer.remove(wsk-> referer.size()-2, 2);
        }
    }

    {
        QRegExp cookie("\nCookie: .[^\r\n]*\r\n");
        if(cookie.indexIn(header, 0))
        {
            wsk-> cookie = cookie.cap(0);
            wsk-> cookie.remove(0, strlen("\nCookie: "));
            wsk-> cookie.remove(wsk-> cookie.size()-2, 2);
        }
    }

    std::cout << wsk->vpath.toStdString() << std::endl;

    return wsk;
}

http_client *Server::LookFor(QTcpSocket *socket)
{
    for(int i=0;i<clients.size();i++)
        if(clients[i]->socket == socket)
            return clients[i];

    return NULL;
}

void Server::responseMgr(http_client *client)
{
    if(client)
    {
        client->socket->write(header(200,page->getPage("/").size()).toAscii());
        client->socket->write(page->getPage("/").toAscii());
        client->socket->close();
    }
    else
        return;
}

void Server::startRead()
{
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    http_client *client = LookFor(socket);

    if(!client)
        return;

    unsigned int readed = socket->bytesAvailable();

    QByteArray data = socket->read(readed);
    client -> buffer += data;

	for(int i=0;i<readed-3;i++)
	{	
        if(data.data()[i] == '\r' && data.data()[i+1] == '\n' && data.data()[i+2] == '\r' && 
            data.data()[i+3] == '\n' && !client->header)
        {
            client -> header = parseQuery(client->buffer);

		    if(true)
			    responseMgr(client);
        }
            
	}

}
